home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Practical Algorithms for Image Analysis
/
Practical Algorithms for Image Analysis.iso
/
LIBIP
/
DESCRIPT.C
< prev
next >
Wrap
C/C++ Source or Header
|
1999-09-11
|
8KB
|
314 lines
/*
* descript.c
*
* Practical Algorithms for Image Analysis
*
* Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
*/
/*
* DESCRIPT
*
* evaluation of Fourier descriptors for a plane curve
* encoded in a set {delta_phi(k), l(k)};
*
* references:
* C. T. Zahn,
* Proc. Joint Intern. Conf. on Artif. Intelligence, May 1969, pp. 621 - 628;
* SLAC Report 70, Stanford Linear Accelerator Center, 1968;
* C. T. Zahn & R. Z. Roskies, IEEE Trans. Comp., Vol C-21, 269 - 281 (1972);
*
* -->the truncated Fourier expansion derived by Z & R is computed
* in form of inner products using array processor functions
*
* -->test shapes (see Z & R):
* four (xdrawfour.c), inverted L (fdzahnl.c)
*
* ---------------------------------------------------------------------------
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "ip.h"
#define EPS 0.00000001
#define SQ2 1.414213562
#define ON 1
#define OFF 0
#define FD_DEBUG ON
/*
* descriptors()
* DESCRIPTION:
* evaluate ZAHN-ROSKIES Fourier descriptors
* ARGUMENTS:
* dphik: delta phik for polygon (float *)
* dlk: delta lk for polygon (float *)
* mcp: length of dphik and dlk (long)
* a_n: Fourier coefficients array (float *)
* b_n: Fourier coefficients array (float *)
* n_order: order of Fourier descriptors to compute (long)
* RETURN VALUE:
* none
*/
void
descriptors (float *dphik, float *dlk, long mcp, float *a_n, float *b_n, long n_order)
{
int k, n_ord;
int fund_flag = OFF;
float real_length, length;
float dc_term, a, b, part_sum;
float *angle;
float *sne, *csn;
float *mag, *phase;
int n;
/*
* compute (in place) running sums of the elements in dlk
* and the corresponding phase angles required in the evaluation
* of the fundamental
*/
if ((sne = (float *) calloc ((int) mcp, sizeof (double))) == NULL) {
printf ("descriptors: memory allocation error for sne\n");
exit (1);
}
if ((csn = (float *) calloc ((int) mcp, sizeof (double))) == NULL) {
printf ("descriptors: memory allocation error for csn\n");
exit (1);
}
if ((angle = (float *) calloc ((int) mcp, sizeof (double))) == NULL) {
printf ("descriptors: memory allocation error for angle\n");
exit (1);
}
/*
* evaluate contour length, based on curvature points
*/
part_sum = *(dlk + 0);
for (k = 1; k < mcp; k++) {
part_sum += *(dlk + k);
*(dlk + k) = part_sum; /* array of partial sums */
}
length = *(dlk + mcp - 1);
for (k = 0; k < mcp; k++)
*(angle + k) = (float) (2 * PI * (*(dlk + k)) / length);
real_length = (float) (0.5 * length);
printf ("\n...length = %f\n", real_length);
/*
* dphik contains elements of delta_phik multiplied by PI/4;
* to speed up computation, factor out PI
*/
for (k = 0; k < mcp; k++)
*(dphik + k) *= (float) 0.25;
#ifdef FD_DEBUG
printf ("...elements of dphik and dlk:\n");
for (k = 0; k < mcp; k++)
printf ("%7.4f %7.4f\n", *(dphik + k), *(dlk + k));
#endif
/*
* compute DC term
*/
vdot (dphik, dlk, &dc_term, mcp);
dc_term = (float) (-PI * (1.0 + dc_term / length));
printf ("...and we have a result for the DC term: %f \n", dc_term);
/*
* compute increasing orders of Fourier coefficients up to n
*/
n = 0;
while (n < n_order) {
for (k = 0; k < mcp; k++) {
if (fabs (*(sne + k) = (float) sin (*(angle + k) * (n + 1))) < EPS)
*(sne + k) = (float) 0.0;
if (fabs (*(csn + k) = (float) cos (*(angle + k) * (n + 1))) < EPS)
*(csn + k) = (float) 0.0;
}
vdot (dphik, sne, &a, mcp);
vdot (dphik, csn, &b, mcp);
*(b_n + n) = (b / (float) (n + 1));
*(a_n + n) = -(a / (float) (n + 1));
n++;
}
printf ("...descriptors up to %dth order are:\n", n_order);
for (n = 0; n < n_order; n++)
printf ("%7.3f %7.3f\n", *(a_n + n), *(b_n + n));
mag = (float *) calloc ((int) n_order, sizeof (float));
phase = (float *) calloc ((int) n_order, sizeof (float));
/*
* calculate xy to polar coordinate transformation
*/
vrtop (a_n, b_n, mag, phase, n_order);
printf ("...polar descriptors up to %ld-th order are:\n", n_order);
for (n_ord = 0; n_ord < (int) n_order; n_ord++) {
if (*(phase + n_ord) < 0.0)
*(phase + n_ord) += (float) (2.0 * PI);
printf ("%7.3f %7.3f\n", *(mag + n_ord), *(phase + n_ord));
}
free (angle);
free (sne);
free (csn);
free (mag);
free (phase);
}
/*
* vdot()
* DESCRIPTION:
* take the dot product of 2 vectors
* and compute the sum
* ARGUMENTS:
* v1: first vector (float *)
* v2: second vector (float *)
* vsum: vector sum (float *)
* vlen: length of vectors (long)
* RETURN VALUE:
* none
*/
void
vdot (float *v1, float *v2, float *vsum, long vlen)
{
float rsum = (float) 0.0;
int i;
for (i = 0; i < vlen; i++)
rsum = rsum + *(v1 + i) * (*(v2 + i));
*vsum = rsum;
}
/*
* vcos()
* DESCRIPTION:
* takes the cosine of a vector
* ARGUMENTS:
* source: input vector (float *) NOTE: radians!!
* dest: output vector (float *)
* vlen: vector length (long)
* RETURN VALUE:
* none
*/
void
vcos (float *source, float *dest, long vlen)
{
int i;
for (i = 0; i < vlen; i++)
*(dest + i) = (float) cos ((double) *(source + i));
}
/*
* vsin()
* DESCRIPTION:
* takes the sine of a vector
* ARGUMENTS:
* source: input vector (float *) NOTE: radians!!
* dest: output vector (float *)
* vlen: vector length (long)
* RETURN VALUE:
* none
*/
void
vsin (float *source, float *dest, long vlen)
{
int i;
for (i = 0; i < vlen; i++)
*(dest + i) = (float) sin ((double) *(source + i));
}
/*
* vrtop()
* DESCRIPTION:
* converts rectangular cartesian
* coordinates to polar
* ARGUMENTS:
* x: input x vector (float *)
* y: input y vector (float *)
* mod: modulus output vector (float *)
* arg: atan2 output vector (float *)
* vlen: vector lengths (long)
* RETURN VALUE:
* none
*/
void
vrtop (float *x, float *y, float *mag, float *phase, long vlen)
{
int i;
for (i = 0; i < vlen; i++) {
*(mag + i) = (float) sqrt ((*(x + i)) * (*(x + i)) + (*(y + i)) * (*(y + i)));
*(phase + i) = (float) atan2 (*(y + i), *(x + i));
if (fabs (*(phase + i)) < EPS)
*(phase + i) = (float) 0.0;
else if (*(phase + i) < (float) 0.0)
*(phase + i) += (float) (2.0 * PI);
}
}
/*
* msdescriptors()
* DESCRIPTION:
* wrapper for call to descriptors()
* ARGUMENTS:
* delta_phik: delta phik for polygon (float *)
* delta_lk: delta lk for polygon (float *)
* mcp: length of dphik and dlk (long)
* a_n: Fourier coefficients array (float *)
* b_n: Fourier coefficients array (float *)
* n_order: order of Fourier descriptors to compute (long)
* RETURN VALUE:
* none
*/
void
msdescriptors (float *delta_phik, float *delta_lk, long mcp, float *a_n, float *b_n, long n_order)
{
int k;
#ifdef FD_DEBUG
printf ("\nevaluation of Fourier descriptors (Zahn & Roskies)\n");
printf ("--------------------------------------------------\n");
printf ("...given: two vectors, delta_phik[] and delta_lk[]\n");
printf (" delta_phik:\n");
for (k = 0; k < (int) mcp; k++) {
printf ("%7.2f ", *(delta_phik + k));
if ((k + 1) % 8 == 0)
printf ("\n");
}
printf ("\n delta_lk:\n");
for (k = 0; k < (int) mcp; k++) {
printf ("%7.2f ", *(delta_lk + k));
if ((k + 1) % 8 == 0)
printf ("\n");
}
#endif
if (n_order > mcp) {
printf ("...polygon only has %ld vertices;");
printf (" cannot yield %ld harmonics!\n", mcp, n_order);
exit (1);
}
descriptors (delta_phik, delta_lk, mcp, a_n, b_n, n_order);
}